/*
 *
 * Copyright 2021-2025 Software Radio Systems Limited
 *
 * This file is part of srsRAN.
 *
 * srsRAN is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of
 * the License, or (at your option) any later version.
 *
 * srsRAN is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * A copy of the GNU Affero General Public License can be found in
 * the LICENSE file in the top-level directory of this distribution
 * and at http://www.gnu.org/licenses/.
 *
 */

#include "srsran/srslog/srslog.h"
#include "fmt/format.h"
#include "fmt/std.h"
#include <gtest/gtest.h>
#include <optional>

class format_optional_test : public ::testing::Test
{
protected:
  void SetUp() override
  {
    // init test's logger
    srslog::init();
    logger.set_level(srslog::basic_levels::debug);
  }

  void TearDown() override
  {
    // flush logger after each test
    srslog::flush();
  }

  srslog::basic_logger& logger = srslog::fetch_basic_logger("TEST", false);
};

TEST_F(format_optional_test, opt_uint32_t)
{
  uint32_t                value           = 4711;
  std::optional<uint32_t> opt_val_present = value;
  std::optional<uint32_t> opt_val_empty   = {};
  logger.debug("Test: value={} opt_value_present={} opt_value_empty={}", value, opt_val_present, opt_val_empty);
  EXPECT_EQ(fmt::format("{}", opt_val_present), "4711");
  EXPECT_EQ(fmt::format("{}", opt_val_empty), "{na}");
  // The following unwanted outputs are generated by the unpatched default formatter of the fmt library
  EXPECT_NE(fmt::format("{}", opt_val_present), "optional(4711)") << "Found unwanted format; unpatched formatter";
  EXPECT_NE(fmt::format("{}", opt_val_empty), "none") << "Found unwanted format; unpatched formatter";
}

TEST_F(format_optional_test, opt_double)
{
  double                value           = 12.345;
  std::optional<double> opt_val_present = value;
  std::optional<double> opt_val_empty   = {};
  logger.debug("Test: value={} opt_value_present={} opt_value_empty={}", value, opt_val_present, opt_val_empty);
  EXPECT_EQ(fmt::format("{}", opt_val_present), "12.345");
  EXPECT_EQ(fmt::format("{}", opt_val_empty), "{na}");
  // The following unwanted outputs are generated by the unpatched default formatter of the fmt library
  EXPECT_NE(fmt::format("{}", opt_val_present), "optional(12.345)") << "Found unwanted format; unpatched formatter";
  EXPECT_NE(fmt::format("{}", opt_val_empty), "none") << "Found unwanted format; unpatched formatter";
}

TEST_F(format_optional_test, opt_double_fmt_spec)
{
  double                value           = 12.345;
  std::optional<double> opt_val_present = value;
  std::optional<double> opt_val_empty   = {};
#define OPT_DOUBLE_FMT_SPEC ":.1f"
  logger.debug("Test: value={" OPT_DOUBLE_FMT_SPEC "} opt_value_present={" OPT_DOUBLE_FMT_SPEC
               "} opt_value_empty={" OPT_DOUBLE_FMT_SPEC "}",
               value,
               opt_val_present,
               opt_val_empty);
  EXPECT_EQ(fmt::format("{" OPT_DOUBLE_FMT_SPEC "}", opt_val_present), "12.3");
  EXPECT_EQ(fmt::format("{" OPT_DOUBLE_FMT_SPEC "}", opt_val_empty), "{na}");
  // The following unwanted outputs are generated by the unpatched default formatter of the fmt library
  EXPECT_NE(fmt::format("{" OPT_DOUBLE_FMT_SPEC "}", opt_val_present), "optional(12.3)")
      << "Found unwanted format; unpatched formatter";
  EXPECT_NE(fmt::format("{" OPT_DOUBLE_FMT_SPEC "}", opt_val_empty), "none")
      << "Found unwanted format; unpatched formatter";
}

int main(int argc, char** argv)
{
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
